package br.ufpb.di.ppgi.persistencia.query;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import br.com.caelum.vraptor.ioc.Component;
import br.ufpb.di.ppgi.negocio.modelo.homologacao.proposta.HomologacaoProposta;
import br.ufpb.di.ppgi.negocio.modelo.proposta.Proposta;
import br.ufpb.di.ppgi.negocio.modelo.proposta.PropostaStatus;
import br.ufpb.di.ppgi.negocio.modelo.usuario.Usuario;
import br.ufpb.di.ppgi.persistencia.domainstore.DomainStore;
import br.ufpb.di.ppgi.persistencia.iquery.IPropostaQuery;
import br.ufpb.di.ppgi.persistencia.pagination.HibernateQueryPagedList;

@Component
public class PropostaQuery extends AbstractJPAHibernateQuery implements IPropostaQuery {

	public PropostaQuery(DomainStore domainStore) {
		super(domainStore);
	}

	private Criteria blank() {
		return createCriteria(Proposta.class).addOrder(Order.desc("id"));
	}

	@Override
	public List<Proposta> listByAlunoId(Long id) {
		return list(
				blank()
				.createAlias("aluno", "a")
				.add(Restrictions.eq("a.id", id))
		);
	}
	
	@Override
	public List<Proposta> listByOrientadorId(Long id) {
		return list(
				blank()
				.createAlias("orientador", "o")
				.add(Restrictions.eq("o.id", id))
		);
	}

	@Override
	public List<Proposta> listByOrientadorIdAtivo(Long id) {
		return list(
				blank()
				.createAlias("orientador", "o")
				.add(Restrictions.eq("o.id", id))
				.add(Restrictions.ne("status", PropostaStatus.FINALIZADA))
		);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Proposta> listPendenciasByUsuario(Usuario usuario) {
		return (List<Proposta>) getSession()
			.createQuery("select pk.proposta from HomologacaoProposta h where h.pk.colegiado = :colegiado and h.respondido = :respondido")
			.setParameter("colegiado", usuario)
			.setBoolean("respondido", false)
			.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<HomologacaoProposta> listPendencias(Proposta proposta) {
		return (List<HomologacaoProposta>) getSession()
			.createQuery("from HomologacaoProposta h where h.pk.proposta.id = :propostaId and h.respondido = :respondido")
			.setLong("propostaId", proposta.getId())
			.setBoolean("respondido", false)
			.list();
	}

	@Override
	public Integer countVotosHomologacao(Proposta proposta, boolean homologado) {
		return count(createCriteria(HomologacaoProposta.class)
				.add(Restrictions.eq("pk.proposta", proposta))
				.add(Restrictions.eq("respondido", true))
				.add(Restrictions.eq("homologado", homologado))
				);				
	}

	@Override
	public Integer countTotalVotos(Proposta proposta) {
		return count(createCriteria(HomologacaoProposta.class)
				.add(Restrictions.eq("pk.proposta", proposta))
				);				
	}
	
	@Override
	public boolean isVotacaoInsuficiente(Proposta proposta) {
		return count(createCriteria(HomologacaoProposta.class)
				.add(Restrictions.eq("pk.proposta", proposta))
				.add(Restrictions.eq("respondido", true))
				)  < 3;	
	}

	@Override
	public List<Proposta> listByStatus(PropostaStatus status) {
		return list(
				blank().add(Restrictions.eq("status", status))
			);
	}

	@Override
	public HibernateQueryPagedList<Proposta> paginarByKeyAndStatusList(
			String key, List<PropostaStatus> statusAceitaveisProposta) {
		
		DetachedCriteria dc = DetachedCriteria.forClass(Proposta.class)
				.add(Restrictions.in("status", statusAceitaveisProposta));
		
		if (key != null && !key.trim().isEmpty())
			dc.add(Restrictions.ilike("titulo", key, MatchMode.ANYWHERE))
			  .add(Restrictions.ilike("resumo", key, MatchMode.ANYWHERE));

		
		return new HibernateQueryPagedList<Proposta>(dc,session);
	}
}
